using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using System;
using System.Collections.ObjectModel;
using System.Windows;
using System.Linq;
using Autodesk.Revit.UI.Selection;

namespace CodRevit.ViewModels
{
    public partial class CurveArrayViewModel : ObservableObject
    {
        private readonly UIApplication _uiapp;
        private readonly Document _doc;
        private readonly Window _window;
        private readonly ExternalEvent _externalEvent;
        private readonly CurveArrayHandler _arrayHandler;

        [ObservableProperty]
        private ObservableCollection<FamilySymbol> _familySymbols;

        [ObservableProperty]
        private FamilySymbol _selectedFamilySymbol;

        [ObservableProperty]
        private double _startOffset = 0;

        [ObservableProperty]
        private double _spacing = 1000;

        [ObservableProperty]
        private string _status = "请选择族类型和模型线";

        public CurveArrayViewModel(UIApplication uiapp, Window window, ExternalEvent externalEvent, CurveArrayHandler arrayHandler)
        {
            _uiapp = uiapp;
            _doc = uiapp.ActiveUIDocument.Document;
            _window = window;
            _externalEvent = externalEvent;
            _arrayHandler = arrayHandler;

            // 获取所有常规模型族类型
            FamilySymbols = new ObservableCollection<FamilySymbol>(
                new FilteredElementCollector(_doc)
                    .OfClass(typeof(FamilySymbol))
                    .OfCategory(BuiltInCategory.OST_GenericModel)
                    .Cast<FamilySymbol>()
                    .OrderBy(f => f.Family.Name)
                    .ThenBy(f => f.Name));

            if (FamilySymbols.Any())
            {
                SelectedFamilySymbol = FamilySymbols.First();
                Status = "请选择模型线";
            }
            else
            {
                Status = "未找到可用的族类型";
            }
        }

        [RelayCommand]
        private void PickCurve()
        {
            if (SelectedFamilySymbol == null)
            {
                Status = "请先选择族类型";
                return;
            }

            var uidoc = _uiapp.ActiveUIDocument;
            try
            {
                _window.Hide();
                var reference = uidoc.Selection.PickObject(
                    ObjectType.Element,
                    new ModelCurveSelectionFilter(),
                    "请选择模型线");

                var curve = _doc.GetElement(reference.ElementId) as CurveElement;
                if (curve != null)
                {
                    _arrayHandler.SetParameters(
                        curve,
                        SelectedFamilySymbol,
                        StartOffset / 304.8,  // 转换为英尺
                        Spacing / 304.8,      // 转换为英尺
                        message => Status = message);
                    _externalEvent.Raise();
                }
            }
            catch (Autodesk.Revit.Exceptions.OperationCanceledException)
            {
                Status = "操作已取消";
            }
            catch (Exception ex)
            {
                Status = $"错误：{ex.Message}";
            }
            finally
            {
                _window.Show();
                _window.Activate();
            }
        }
    }

    public class CurveArrayHandler : IExternalEventHandler
    {
        private readonly Document _doc;
        private CurveElement? _curve;
        private FamilySymbol? _familySymbol;
        private double _startOffset;
        private double _spacing;
        private Action<string>? _statusCallback;

        public CurveArrayHandler(Document doc)
        {
            _doc = doc;
        }

        public void SetParameters(
            CurveElement curve,
            FamilySymbol familySymbol,
            double startOffset,
            double spacing,
            Action<string> statusCallback)
        {
            _curve = curve;
            _familySymbol = familySymbol;
            _startOffset = startOffset;
            _spacing = spacing;
            _statusCallback = statusCallback;
        }

        public void Execute(UIApplication app)
        {
            if (_curve == null || _familySymbol == null)
            {
                _statusCallback?.Invoke("错误：未设置曲线或族类型");
                return;
            }

            try
            {
                using (Transaction trans = new Transaction(_doc, "曲线阵列"))
                {
                    trans.Start();

                    if (!_familySymbol.IsActive)
                    {
                        _familySymbol.Activate();
                    }

                    var curve = _curve.GeometryCurve;
                    double curveLength = curve.Length;

                    // 如果起始偏移大于曲线长度，直接返回
                    if (_startOffset >= curveLength)
                    {
                        _statusCallback?.Invoke("起始偏移距离超过曲线长度");
                        trans.RollBack();
                        return;
                    }

                    int successCount = 0;

                    // 计算可以放置的实例数量
                    int instanceCount = (int)Math.Floor((curveLength - _startOffset) / _spacing) + 1;

                    // 获取视图
                    View view = _doc.ActiveView;

                    for (int i = 0; i < instanceCount; i++)
                    {
                        try
                        {
                            // 计算当前距离
                            double currentDistance = _startOffset + (i * _spacing);
                            if (currentDistance > curveLength)
                                break;

                            // 获取曲线上的点和切线方向
                            XYZ point;
                            XYZ tangent;

                            if (curve is Line)
                            {
                                // 如果是直线
                                XYZ startPoint = curve.GetEndPoint(0);
                                XYZ endPoint = curve.GetEndPoint(1);
                                tangent = (endPoint - startPoint).Normalize();
                                point = startPoint + tangent * currentDistance;
                            }
                            else if (curve is Arc arc)
                            {
                                // 检查是否是封闭圆弧
                                if (Math.Abs(arc.Length - 2 * Math.PI * arc.Radius) < 0.0001)
                                {
                                    // 创建一个新的非封闭圆弧
                                    try
                                    {
                                        // 计算当前角度
                                        double ratio = currentDistance / curveLength;
                                        double angle = ratio * 2 * Math.PI;

                                        // 使用参数方程计算点的位置
                                        XYZ center = arc.Center;
                                        double radius = arc.Radius;
                                        XYZ xDir = arc.XDirection;
                                        XYZ yDir = arc.YDirection;

                                        // 计算点的位置
                                        point = center + radius * (Math.Cos(angle) * xDir + Math.Sin(angle) * yDir);

                                        // 计算切线方向（垂直于半径方向）
                                        tangent = (-Math.Sin(angle) * xDir + Math.Cos(angle) * yDir).Normalize();
                                    }
                                    catch
                                    {
                                        // 如果参数方程失败，使用简单的线性插值
                                        double startParam = arc.GetEndParameter(0);
                                        double endParam = arc.GetEndParameter(1);
                                        double paramRange = endParam - startParam;
                                        double targetParam = startParam + (currentDistance / curveLength) * paramRange;

                                        point = arc.Evaluate(targetParam, false);
                                        Transform derivatives = arc.ComputeDerivatives(targetParam, false);
                                        tangent = derivatives.BasisX.Normalize();
                                    }
                                }
                                else
                                {
                                    // 非封闭圆弧使用原有方法
                                    double startParam = curve.GetEndParameter(0);
                                    double endParam = curve.GetEndParameter(1);
                                    double paramRange = endParam - startParam;

                                    double ratio = currentDistance / curveLength;
                                    double targetParam = startParam + ratio * paramRange;

                                    try
                                    {
                                        point = curve.Evaluate(targetParam, false);
                                        Transform derivatives = curve.ComputeDerivatives(targetParam, false);
                                        tangent = derivatives.BasisX.Normalize();
                                    }
                                    catch
                                    {
                                        point = curve.GetEndPoint(0).Add(curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Multiply(ratio));
                                        tangent = curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Normalize();
                                    }
                                }
                            }
                            else if (curve is Ellipse ellipse)
                            {
                                // 检查是否是封闭椭圆
                                if (Math.Abs(ellipse.GetEndParameter(1) - ellipse.GetEndParameter(0) - 2 * Math.PI) < 0.0001)
                                {
                                    try
                                    {
                                        // 计算当前角度
                                        double ratio = currentDistance / curveLength;
                                        double targetParam;

                                        // 将椭圆分成两段处理
                                        if (ratio <= 0.5)
                                        {
                                            // 第一段：0到π
                                            targetParam = (ratio * 2) * Math.PI;
                                        }
                                        else
                                        {
                                            // 第二段：π到2π
                                            targetParam = ((ratio - 0.5) * 2) * Math.PI + Math.PI;
                                        }

                                        // 确保参数不会超过2π
                                        if (targetParam >= 2 * Math.PI)
                                        {
                                            targetParam = 2 * Math.PI - 0.0001;
                                        }

                                        // 使用参数计算点和切线
                                        point = ellipse.Evaluate(targetParam, false);
                                        Transform derivatives = ellipse.ComputeDerivatives(targetParam, false);
                                        tangent = derivatives.BasisX.Normalize();
                                    }
                                    catch
                                    {
                                        // 如果失败，使用简单的线性插值
                                        double ratio = currentDistance / curveLength;
                                        point = curve.GetEndPoint(0).Add(curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Multiply(ratio));
                                        tangent = curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Normalize();
                                    }
                                }
                                else
                                {
                                    // 非封闭椭圆使用原有方法
                                    double startParam = curve.GetEndParameter(0);
                                    double endParam = curve.GetEndParameter(1);
                                    double paramRange = endParam - startParam;

                                    double ratio = currentDistance / curveLength;
                                    double targetParam = startParam + ratio * paramRange;

                                    try
                                    {
                                        point = curve.Evaluate(targetParam, false);
                                        Transform derivatives = curve.ComputeDerivatives(targetParam, false);
                                        tangent = derivatives.BasisX.Normalize();
                                    }
                                    catch
                                    {
                                        point = curve.GetEndPoint(0).Add(curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Multiply(ratio));
                                        tangent = curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Normalize();
                                    }
                                }
                            }
                            else
                            {
                                // 其他类型曲线使用原有方法
                                double startParam = curve.GetEndParameter(0);
                                double endParam = curve.GetEndParameter(1);
                                double paramRange = endParam - startParam;

                                double ratio = currentDistance / curveLength;
                                double targetParam = startParam + ratio * paramRange;

                                try
                                {
                                    point = curve.Evaluate(targetParam, false);
                                    Transform derivatives = curve.ComputeDerivatives(targetParam, false);
                                    tangent = derivatives.BasisX.Normalize();
                                }
                                catch
                                {
                                    point = curve.GetEndPoint(0).Add(curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Multiply(ratio));
                                    tangent = curve.GetEndPoint(1).Subtract(curve.GetEndPoint(0)).Normalize();
                                }
                            }

                            // 创建族实例并设置方向
                            FamilyInstance instance = _doc.Create.NewFamilyInstance(
                                point,
                                _familySymbol,
                                tangent,
                                view,
                                Autodesk.Revit.DB.Structure.StructuralType.NonStructural);

                            successCount++;
                        }
                        catch (Exception ex)
                        {
                            _statusCallback?.Invoke($"放置第 {i + 1} 个实例失败: {ex.Message}");
                            continue;
                        }
                    }

                    trans.Commit();
                    _statusCallback?.Invoke($"成功放置 {successCount} 个族实例");
                }
            }
            catch (Exception ex)
            {
                _statusCallback?.Invoke($"执行失败: {ex.Message}");
            }
        }

        public string GetName()
        {
            return "CurveArrayCreator";
        }
    }
}